import os
import json
import time
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, generics
from django.http import StreamingHttpResponse
from openai import OpenAI
from django.conf import settings
from .models import *
from examination_questions_app.models import *
from user_app.utils import *
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from rest_framework.pagination import PageNumberPagination
from examination_questions_app.models import *

class MessagePagination(PageNumberPagination):
    """
    会话消息分页器
    """
    page_query_param = 'page'
    page_size_query_param = 'size'
    page_size = 10

nurse_system_prompt = """
你是一名专业的护士考试辅导老师，负责为护士研究生考试的题目提供答案及详细解释。当用户提出一道题时，你需要先给出正确答案选项，然后详细解释选择该答案的原因，同时说明其他选项错误的理由。如果用户追问，直接回答即可
"""



def get_response(messages, stream=False):
    client = OpenAI(
        # 若没有配置环境变量，请用阿里云百炼API Key将下行替换为：api_key="sk-xxx",
        api_key=settings.DASHSCOPE_API_KEY,
        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    )
    # 模型列表：https://help.aliyun.com/zh/model-studio/getting-started/models
    if stream:
        return client.chat.completions.create(model="qwen-plus", messages=messages, stream=True)
    else:
        return client.chat.completions.create(model="qwen-plus", messages=messages)


class createConversationView(APIView):
    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter(
                'Authorization', 
                openapi.IN_HEADER, 
                description="用户认证Token", 
                type=openapi.TYPE_STRING, 
                required=True
            ),
        ],
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={},
            description="无请求体参数"
        ),
        responses={
            200: openapi.Response(
                description="成功创建对话",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='成功信息'),
                        'data': openapi.Schema(type=openapi.TYPE_OBJECT, description='会话数据', properties={
                            'conversation_id': openapi.Schema(type=openapi.TYPE_STRING, description='会话ID'),
                            'title': openapi.Schema(type=openapi.TYPE_STRING, description='会话标题')
                        })
                    }
                )
            ),
            401: openapi.Response(
                description="未授权访问",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='错误信息')
                    }
                )
            )
        }
    )
    def post(self, request):
        """
        创建对话接口
        """
        token = request.META.get("HTTP_AUTHORIZATION")
        user_id = verify_token(token).get("id")
        conversation = AiConversation.objects.create(user_id=user_id)
        ConversationMessage.objects.create(conversation=conversation, role="system", content=nurse_system_prompt)
        return Response({"message": "创建成功", "data": {"conversation_id": conversation.id, "title": conversation.title}}, status=status.HTTP_200_OK)
        

        
# 删除会话
class deleteConversation(APIView):
    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter(
                'Authorization', 
                openapi.IN_HEADER, 
                description="用户认证Token", 
                type=openapi.TYPE_STRING, 
                required=True
            ),
        ],
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'conversation_id': openapi.Schema(type=openapi.TYPE_STRING, description='会话ID')
            },
            required=['conversation_id']
        ),
        responses={
            200: openapi.Response(
                description="成功删除会话",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='成功信息')
                    }
                )
            ),
            400: openapi.Response(
                description="会话不存在",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='错误信息')
                    }
                )
            ),
            401: openapi.Response(
                description="未授权访问",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='错误信息')
                    }
                )
            )
        }
    )
    def delete(self, request):
        """
        删除会话接口
        """
        token = request.META.get("HTTP_AUTHORIZATION")
        user_id = verify_token(token).get("id")
        conversation_id = request.data.get("conversation_id")
        conversation = AiConversation.objects.filter(pk=conversation_id, user_id=user_id).first()
        if conversation:
            conversation.delete()
            # 删除会话中的所有消息
            ConversationMessage.objects.filter(conversation_id=conversation_id).delete()
            return Response({"message": "删除成功"}, status=status.HTTP_200_OK)
        else:
            return Response({"message": "会话不存在"}, status=status.HTTP_400_BAD_REQUEST)

## 修改会话标题
class updateConversationTitleView(APIView):
    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter(
                'Authorization', 
                openapi.IN_HEADER, 
                description="用户认证Token", 
                type=openapi.TYPE_STRING, 
                required=True
            ),
        ],
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'conversation_id': openapi.Schema(type=openapi.TYPE_STRING, description='会话ID'),
                'title': openapi.Schema(type=openapi.TYPE_STRING, description='新的会话标题')
            },
            required=['conversation_id', 'title']
        ),
        responses={
            200: openapi.Response(
                description="成功修改会话标题",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='成功信息')
                    }
                )
            ),
            400: openapi.Response(
                description="会话不存在",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='错误信息')
                    }
                )
            ),
            401: openapi.Response(
                description="未授权访问",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='错误信息')
                    }
                )
            )
        }
    )
    def post(self, request):
        """
        修改会话标题接口
        """
        token = request.META.get("HTTP_AUTHORIZATION")
        user_id = verify_token(token).get("id")
        conversation_id = request.data.get("conversation_id")
        title = request.data.get("title")
        conversation = AiConversation.objects.filter(pk=conversation_id, user_id=user_id).first()
        if conversation:
            conversation.title = title
            conversation.save()
            return Response({"message": "修改成功"}, status=status.HTTP_200_OK)
        else:
            return Response({"message": "会话不存在"}, status=status.HTTP_400_BAD_REQUEST)

### 获取会话列表
class getConversationListView(APIView):
    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter(
                'Authorization', 
                openapi.IN_HEADER, 
                description="用户认证Token", 
                type=openapi.TYPE_STRING, 
                required=True
            ),
            openapi.Parameter(
                'page', 
                openapi.IN_QUERY, 
                description="页码", 
                type=openapi.TYPE_INTEGER, 
                required=False, 
                default=1
            ),
            openapi.Parameter(
                'size', 
                openapi.IN_QUERY, 
                description="每页条数", 
                type=openapi.TYPE_INTEGER, 
                required=False, 
                default=10
            ),
        ],
        responses={
            200: openapi.Response(
                description="成功获取会话列表",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'conversations': openapi.Schema(
                            type=openapi.TYPE_ARRAY,
                            items=openapi.Schema(
                                type=openapi.TYPE_OBJECT,
                                properties={
                                    'id': openapi.Schema(type=openapi.TYPE_STRING, description='会话ID'),
                                    'title': openapi.Schema(type=openapi.TYPE_STRING, description='会话标题'),
                                    'created_at': openapi.Schema(type=openapi.TYPE_INTEGER, description='创建时间戳(毫秒)')
                                }
                            )
                        ),
                        'count': openapi.Schema(type=openapi.TYPE_INTEGER, description='总记录数'),
                        'next': openapi.Schema(type=openapi.TYPE_STRING, description='下一页URL', nullable=True),
                        'previous': openapi.Schema(type=openapi.TYPE_STRING, description='上一页URL', nullable=True),
                        'page': openapi.Schema(type=openapi.TYPE_INTEGER, description='当前页码'),
                        'size': openapi.Schema(type=openapi.TYPE_INTEGER, description='每页条数'),
                        'pages': openapi.Schema(type=openapi.TYPE_INTEGER, description='总页数')
                    }
                )
            ),
            401: openapi.Response(
                description="未授权访问",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='错误信息')
                    }
                )
            )
        }
    )
    def get(self, request):
        """
        获取会话列表接口
        """
        token = request.META.get("HTTP_AUTHORIZATION")
        user_id = verify_token(token).get("id")
        
        # 获取分页参数
        page = request.query_params.get('page', 1)
        size = request.query_params.get('size', 10)
        
        # 转换分页参数为整数
        try:
            page = int(page)
            size = int(size)
        except ValueError:
            page = 1
            size = 10
        
        # 查询所有会话
        queryset = AiConversation.objects.filter(user_id=user_id).order_by('-created_at')
        
        # 计算分页信息
        total_count = queryset.count()
        total_pages = (total_count + size - 1) // size
        
        # 确保页码在有效范围内
        if page < 1:
            page = 1
        elif page > total_pages:
            page = max(1, total_pages)
        
        # 应用分页
        start = (page - 1) * size
        end = start + size
        paginated_conversations = queryset[start:end].values("id", "title", "created_at")
        
        # 转换时间戳
        conversations_data = []
        for conversation in paginated_conversations:
            conversation["created_at"] = int(conversation["created_at"].timestamp() * 1000)
            conversations_data.append(conversation)
        
        # 构建分页响应
        response_data = {
            'conversations': conversations_data,
            'count': total_count,
            'next': f'?page={page+1}&size={size}' if page < total_pages else None,
            'previous': f'?page={page-1}&size={size}' if page > 1 else None,
            'page': page,
            'size': size,
            'pages': total_pages
        }
        
        return Response(response_data, status=status.HTTP_200_OK)

### 根据会话id获取用户的对话记录
class getConversationMessageView(APIView):
    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter(
                'conversation_id', 
                openapi.IN_QUERY, 
                description="会话ID", 
                type=openapi.TYPE_STRING, 
                required=True
            ),
            openapi.Parameter(
                'page', 
                openapi.IN_QUERY, 
                description="页码", 
                type=openapi.TYPE_INTEGER, 
                required=False, 
                default=1
            ),
            openapi.Parameter(
                'size', 
                openapi.IN_QUERY, 
                description="每页条数", 
                type=openapi.TYPE_INTEGER, 
                required=False, 
                default=10
            ),
            openapi.Parameter(
                'Authorization', 
                openapi.IN_HEADER, 
                description="用户认证Token", 
                type=openapi.TYPE_STRING, 
                required=True
            ),
        ],
        responses={
            200: openapi.Response(
                description="成功获取对话记录",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'messages': openapi.Schema(
                            type=openapi.TYPE_ARRAY,
                            items=openapi.Schema(
                                type=openapi.TYPE_OBJECT,
                                properties={
                                    'role': openapi.Schema(type=openapi.TYPE_STRING, description='角色(user/assistant/system)'),
                                    'message': openapi.Schema(type=openapi.TYPE_STRING, description='消息内容'),
                                    'created_at': openapi.Schema(type=openapi.TYPE_INTEGER, description='创建时间戳(毫秒)')
                                }
                            )
                        ),
                        'count': openapi.Schema(type=openapi.TYPE_INTEGER, description='总记录数'),
                        'next': openapi.Schema(type=openapi.TYPE_STRING, description='下一页URL', nullable=True),
                        'previous': openapi.Schema(type=openapi.TYPE_STRING, description='上一页URL', nullable=True),
                        'page': openapi.Schema(type=openapi.TYPE_INTEGER, description='当前页码'),
                        'size': openapi.Schema(type=openapi.TYPE_INTEGER, description='每页条数'),
                        'pages': openapi.Schema(type=openapi.TYPE_INTEGER, description='总页数')
                    }
                )
            ),
            400: openapi.Response(
                description="会话不存在",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='错误信息')
                    }
                )
            )
        }
    )
    def get(self, request):
        """
        根据会话id获取用户的对话记录接口
        """
        token = request.META.get("HTTP_AUTHORIZATION")
        user_id = verify_token(token).get("id")
        # 同时支持从 query_params 和 data 中获取，以保持向后兼容
        conversation_id = request.query_params.get("conversation_id") or request.data.get("conversation_id")
        conversation = AiConversation.objects.filter(pk=conversation_id, user_id=user_id).first()
        if conversation:
            # 获取分页参数
            page = request.query_params.get('page', 1)
            size = request.query_params.get('size', 10)
            
            # 转换分页参数为整数
            try:
                page = int(page)
                size = int(size)
            except ValueError:
                page = 1
                size = 10
            
            # 分页查询消息.倒序
            queryset = ConversationMessage.objects.filter(conversation_id=conversation_id).order_by('-created_at')
            # queryset = ConversationMessage.objects.filter(conversation_id=conversation_id).order_by('created_at')
            
            # 手动应用分页逻辑
            start = (page - 1) * size
            end = start + size
            paginated_messages = queryset[start:end]
            
            # 计算总页数
            total_count = queryset.count()
            total_pages = (total_count + size - 1) // size
            
            # 序列化消息
            contents_data = []
            for content in paginated_messages.values("role", "content", "created_at"):
                if content["role"] == "system":
                    continue  # 跳过created_at为None的消息
                content["timestamp"] = int(content["created_at"].timestamp() * 1000)
                contents_data.append(content)
            
            # 构建分页响应
            response_data = {
                'messages': contents_data,
                'count': total_count,
                'next': f'?page={page+1}&size={size}&conversation_id={conversation_id}' if page < total_pages else None,
                'previous': f'?page={page-1}&size={size}&conversation_id={conversation_id}' if page > 1 else None,
                'page': page,
                'size': size,
                'pages': total_pages
            }
            
            return Response(response_data, status=status.HTTP_200_OK)
        else:
            return Response({"message": "会话不存在"}, status=status.HTTP_400_BAD_REQUEST)


class multiRoundDialogueView(APIView):
    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter(
                'Authorization', 
                openapi.IN_HEADER, 
                description="用户认证Token", 
                type=openapi.TYPE_STRING, 
                required=True
            ),
        ],
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'content': openapi.Schema(type=openapi.TYPE_STRING, description='用户提问内容'),
                'conversation_id': openapi.Schema(type=openapi.TYPE_STRING, description='会话ID'),
                'params': openapi.Schema(type=openapi.TYPE_OBJECT, description='可选参数')
            },
            required=['content', 'conversation_id']
        ),
        responses={
            200: openapi.Response(
                description="流式响应，返回text/event-stream格式",
                schema=openapi.Schema(
                    type=openapi.TYPE_STRING,
                    description="SSE格式的流式响应，包含content和done事件"
                ),
                content_type="text/event-stream"
            ),
            400: openapi.Response(
                description="会话不存在",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='错误信息')
                    }
                )
            ),
            401: openapi.Response(
                description="未授权访问",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='错误信息')
                    }
                )
            )
        }
    )
    def post(self, request):
        """
        创建新的对话记录 - 使用SSE实现流式输出
        """
        user_input = request.data.get("content")  # 从请求数据中获取content字段
        token = request.META.get("HTTP_AUTHORIZATION")
        conversation_id = request.data.get("conversation_id")
        user_id = verify_token(token).get("id")
        params = request.data.get("params")
        conversation = AiConversation.objects.filter(pk=conversation_id, user_id=user_id).first()
        
        if not conversation:
            return Response({"message": "会话不存在"}, status=status.HTTP_400_BAD_REQUEST)
        if params:
            if params.get("regenerate"):
                #ConversationMessage中删除最近两条消息
                conversation_message = ConversationMessage.objects.filter(conversation_id=conversation_id).order_by('-created_at').first()
                if conversation_message.role == "user":
                    # 最近一条是用户信息，只删除用户信息即可
                    conversation_message.delete()
                else:
                    # 如果最近一条不是用户信息，删除最近两条消息
                    conversation_message.delete()
                    ConversationMessage.objects.filter(conversation_id=conversation_id).order_by('-created_at').first().delete()
            if params.get("question"):
                    ConversationMessage.objects.create(conversation=conversation, role="user", content=str(params.get("question")))
        # 保存用户消息
        ConversationMessage.objects.create(conversation=conversation, role="user", content=user_input)
        # 获取所有对话历史
        _messages = ConversationMessage.objects.filter(conversation_id=conversation_id).values("role", "content", "created_at")
        # messages = [{"role": message.get("role"), "content": message.get("content")} for message in messages]
        messages = [{'role': 'system', 'content': nurse_system_prompt}]  # 保留第一个消息，其他消息解析问题
        for message in  _messages if len(_messages) <=19 else _messages[len(_messages)-19:len(_messages)]:  # 保留第一个消息，其他消息解析问题
            content = message.get("content")
            # 安全地尝试将字符串解析为字典
            try:
                # 检查是否是JSON格式的字典字符串
                content_dict = eval(content)
                if isinstance(content_dict, dict):
                    question_id = content_dict.get('question').get('id')
                    if question_id:
                        question = ExaminationQuestions.objects.filter(pk=question_id).values('question','options','explanation').first()
                        if question:
                            content = f'问题：{question.get("question")}，选项：{question.get("options")},解析：{question.get("explanation")}'
            except:
                # 如果解析失败或不是字典类型，保持原内容不变
                pass
            messages.append({"role": message.get("role"), "content": content})
        # 定义流式响应的生成器函数
        def stream_generator():
            full_response = ""
            # 获取流式响应
            stream = get_response(messages, stream=True)
            
            # 处理流式响应
            for chunk in stream:
                if hasattr(chunk.choices[0].delta, 'content') and chunk.choices[0].delta.content:
                    content = chunk.choices[0].delta.content
                    full_response += content
                    # 发送SSE事件，ensure_ascii=False确保中文正常显示
                    yield f"data: {json.dumps({'content': content}, ensure_ascii=False)}\n\n"
                    # 小延迟，使效果更流畅
                    time.sleep(0.05)
            
            # 安全检查，确保full_response不为空
            if not full_response:
                # 如果流式响应为空，尝试获取非流式完整响应
                try:
                    non_stream_response = get_response(messages, stream=False)
                    if hasattr(non_stream_response.choices[0].message, 'content'):
                        full_response = non_stream_response.choices[0].message.content
                except Exception as e:
                    print(f"获取完整响应失败: {e}")
            
            # 保存完整响应到数据库
            if full_response:
                ConversationMessage.objects.create(conversation=conversation, role="assistant", content=full_response)
            # 发送结束事件
            yield f"data: {json.dumps({'done': True}, ensure_ascii=False)}\n\n"
        
        # 返回流式HTTP响应
        response = StreamingHttpResponse(stream_generator(), content_type='text/event-stream')
        response['Cache-Control'] = 'no-cache'
        response['X-Accel-Buffering'] = 'no'  # 禁用代理缓冲
        return response


### 清空对话记录
class clearDialogueView(APIView):
    @swagger_auto_schema(
        manual_parameters=[
            openapi.Parameter(
                'Authorization', 
                openapi.IN_HEADER, 
                description="用户认证Token", 
                type=openapi.TYPE_STRING, 
                required=True
            ),
        ],
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'conversation_id': openapi.Schema(type=openapi.TYPE_STRING, description='会话ID')
            },
            required=['conversation_id']
        ),
        responses={
            200: openapi.Response(
                description="对话记录清空成功",
                schema=openapi.Schema(
                    type=openapi.TYPE_OBJECT,
                    properties={
                        'message': openapi.Schema(type=openapi.TYPE_STRING, description='成功消息')
                    }
                )
            ),
            400: openapi.Response(description="会话不存在"),
            401: openapi.Response(description="未授权访问")
        }
    )
    def post(self, request):
        """
        清空对话记录
        """
        conversation_id = request.data.get("conversation_id")
        token = request.META.get("HTTP_AUTHORIZATION")
        user_id = verify_token(token).get("id")
        conversation = AiConversation.objects.filter(pk=conversation_id, user_id=user_id).first()
        if not conversation:
            return Response({"message": "会话不存在"}, status=status.HTTP_400_BAD_REQUEST)
        ConversationMessage.objects.filter(conversation_id=conversation_id).delete()
        return Response({"message": "对话记录清空成功"}, status=status.HTTP_200_OK)